# --! coding=utf-8 !--
# coding=utf-8
# Copyright (c) [2025] [2578713815@qq.com]
# [AHPU_EQM] is licensed under Mulan PSL v2.
"""
本地数据 io 与 网络数据处理工具库\n
author: <2578713815@qq.com>\n
"""
import datetime
import json
import os
from typing import Set, Tuple, Any, List, Union
from CONFIG import settings
import csv
import pandas as pd
import random
import requests
import re


def get_users_data(file_path: str = settings.USERS_DATA_PATH) -> list:
	"""
	读取用户数据
	:param file_path: 用户数据文件路径
	:return: 所有用户信息的列表
	"""
	with open(file_path, 'r', encoding='utf-8') as f:
		_users_ = csv.reader(f, delimiter=',')
		_users_data_ = []
		for row in _users_:
			_users_data_.append(row)
	return _users_data_[1:]


def get_need_to_request_info(list_data: list) -> List[Tuple[Any, Any]]:
	"""
	获取需要监控的楼房号信息
	:param list_data: 从用户数据读取到的信息
	:return: 需要监控的楼房号集合
	"""
	_need_to_request_info_ = []
	for _data_ in list_data:
		_info_ = (_data_[1], _data_[2])
		_need_to_request_info_.append(_info_)
	_need_to_request_info_ = list(set(_need_to_request_info_))
	return _need_to_request_info_


def get_json_info(file_path: str) -> json:
	"""
	获取json文件中的所有信息
	:param file_path: 文件路径
	:return:
	"""
	with open(file_path, 'r', encoding='utf-8') as f:
		_json_data_ = json.load(f)
	return _json_data_


def save_data_to_csv(data_list: list, save_path: str) -> None:
	"""
	将数据写入csv文件
	:param save_path: 保存信息的文件路径
	:param data_list: 需要写入的数据列表
	:return:
	"""
	with open(save_path, 'w', encoding='utf-8', newline='') as f:
		csv_writer = csv.writer(f, delimiter=',')
		for _data in data_list:
			csv_writer.writerow(_data)


def get_user_data_with_mode(_user_data_: list) -> list:
	"""
	将不同模式的用户数据分开取出
	:param _user_data_: 用户数据
	:return:
	"""
	_user_mode_0_ = []
	_user_mode_1_ = []
	_user_mode_2_ = []
	_user_mode_3_ = []
	_user_mode_4_ = []
	for _i_ in _user_data_:
		if _i_[3] == '0':
			_user_mode_0_.append(_i_)
		elif _i_[3] == '1':
			_user_mode_1_.append(_i_)
		elif _i_[3] == '2':
			_user_mode_2_.append(_i_)
		elif _i_[3] == '3':
			_user_mode_3_.append(_i_)
		elif _i_[3] == '4':
			_user_mode_4_.append(_i_)
	_user_mode_list_ = [_user_mode_0_, _user_mode_1_, _user_mode_2_, _user_mode_3_, _user_mode_4_]
	return _user_mode_list_


def set_user_info_statu(user: str, build: str, room: str, mode: str, file_path: str = settings.USERS_DATA_PATH) -> None:
	"""
	用于在当日信息发送过后,将信息状态改为1
	:param file_path: 用户数据文件路径
	:param user: 用户账号
	:param build: 楼栋号
	:param room: 房间号
	:param mode: 消息模式
	:return:
	"""
	df = pd.read_csv(file_path, dtype=str)
	df.loc[(df["build"] == build) & (df["room"] == room) & (df["user"] == user) & (df["mode"] == mode), "statu"] = "1"
	df.to_csv(settings.USERS_DATA_PATH, index=False, header=True)


def clean_user_info_statu(file_path: str = settings.USERS_DATA_PATH) -> None:
	"""
	用于在0点将所有用户的发送数据状态改为0
	:param file_path:
	:return:
	"""
	df = pd.read_csv(file_path)
	df["statu"] = ["0"]*len(df)
	df.to_csv(file_path, index=False)


def get_electric_with_build_room(build: str, room, file_path: str = settings.DATA_PATH) -> float:
	"""
	从电量数据库中获取指定楼栋，房间的电量信息
	:param file_path: 电量数据文件
	:param build: 楼栋号
	:param room: 房间号
	:return: 读取正常的情况下，返回电量 | 读取失败返回-999.
	"""
	df = pd.read_csv(file_path, dtype=str)
	select_row = df[(df["build"] == build) & (df["room"] == room)]
	if select_row.empty:
		# 如果查询数据为空
		build_id_info = get_json_info(settings.BUILDINGS_PATH)
		build_code = build_id_info[build]
		# 请求数据
		electric = request_data(build_name=build, room_id=room, build_code=build_code)
		if electric:
			save_row = {"build": f"{build}", "room": f"{room}", "electric": f"{electric[0]}"}
			print(settings.BLUE + f">>> Save data: {save_row}" + settings.RESET)
			now = datetime.datetime.now()
			append_log(f"Save new data: {save_row} | {now.strftime('%Y-%m-%d %H:%M:%S')}")
			df = df._append(save_row, ignore_index=True)
			df.to_csv(file_path, index=False, header=True)
			return float(electric[0])
		else:
			return -999.
	else:
		# 如果查询到了数据
		try:
			res = select_row.iloc[0][2]
			return float(res)
		except Exception as e:
			print(settings.RED + f">>> Error:{e}" + settings.RESET)
			return -999.


def append_log(info: str, file_path: str = settings.LOG_PATH) -> None:
	"""
	将信息写入日志文件
	:param info: 待写入的信息
	:param file_path: 日志文件路径
	:return:
	"""
	if not os.path.exists(file_path):
		with open(file_path, 'w', encoding='utf-8') as f:
			f.write("")
	with open(file_path, 'a', encoding='utf-8') as f:
		f.write(info + '\n')


def request_data(room_id, build_code, build_name) -> Union[List[Any], bool]:
	"""
	查询函数，根据楼房号，楼栋名查询电量
	:param room_id: 房间号
	:param build_code: 楼栋码
	:param build_name: 楼栋名
	:return:
	"""
	json_data = {
		"query_elec_roominfo": {
			"aid": "0030000000002501",
			"account": random.choice(settings.ACCOUNT_LIST),
			"room": {"roomid": room_id, "room": room_id},
			"floor": {"floorid": "", "floor": ""},
			"area": {"area": "安徽工程大学", "areaname": "安徽工程大学"},
			"building": {"buildingid": build_code, "building": build_name}
		}
	}
	form_data = {
		"jsondata": json.dumps(json_data),
		"funname": "synjones.onecard.query.elec.roominfo",
		"json": "true"
	}
	print(settings.BLUE + ">>> Updating..." + settings.RESET)
	response = requests.post(settings.URL, headers=settings.HEADERS, data=form_data)
	if response.status_code == 200:
		json_response = json.loads(response.text)
		res = json_response['query_elec_roominfo']['errmsg']
		electric = re.findall(r'.*?(\d+.\d+)', res)
		return electric
	else:
		print(settings.RED + f">>> Network exception: {response.status_code}" + settings.RESET)
		return False
